﻿# ----------------------------- #
# Exchange Server Configuration #
# ----------------------------- #
param([string]$virtualMachineService, [string]$virtualMachineName)

# Return mailbox identity list
function Get-MailboxIdentities($mailboxes)
{
	$result = @();
	foreach ($mailbox in $mailboxes.mailbox)
	{
		$result += $mailbox.identity
	}
	return $result
}

# Return mailbox alias list
function Get-MailboxAliases($mailboxes)
{
	$result = @();
	foreach ($mailbox in $mailboxes.Mailbox)
	{
		$result += $mailbox.Alias
	}
	return $result
}

Write-Information "Virtual machine '$virtualMachineName' Exchange Server '$($script.type)' configuration ... " -NoNewLine $true
$userName = $subscription.virtualMachines.adminUserName
$password = $subscription.virtualMachines.password
$netBiosDomain = $subscription.virtualMachines.netBiosDomain
$uri = Get-AzureWinRMUri -ServiceName $virtualMachineService -Name $virtualMachineName
$credential = New-Object System.Management.Automation.PSCredential(($netBiosDomain + "\" + $userName), (ConvertTo-SecureString $password -AsPlainText -Force))
$session = New-PSSession -ComputerName $uri[0].DnsSafeHost -Credential $credential -Port (Get-VirtualMachineInstanceEndpointPort $subscription $virtualMachineName) -UseSSL -Authentication Credssp
switch ($script.type)
{
	"Prepare"
	{
		Invoke-Command -Session $session -ScriptBlock {
			# ADDS preparation required features
			$result = Install-WindowsFeature RSAT-ADDS -Restart:$false -WarningAction Ignore
			# Mailbox & Client Access server role required features
			$result = Install-WindowsFeature AS-HTTP-Activation,Desktop-Experience,NET-Framework-45-Features,RPC-over-HTTP-proxy,RSAT-Clustering,RSAT-Clustering-CmdInterface,RSAT-Clustering-Mgmt,RSAT-Clustering-PowerShell,Web-Mgmt-Console,WAS-Process-Model,Web-Asp-Net45,Web-Basic-Auth,Web-Client-Auth,Web-Digest-Auth,Web-Dir-Browsing,Web-Dyn-Compression,Web-Http-Errors,Web-Http-Logging,Web-Http-Redirect,Web-Http-Tracing,Web-ISAPI-Ext,Web-ISAPI-Filter,Web-Lgcy-Mgmt-Console,Web-Metabase,Web-Mgmt-Console,Web-Mgmt-Service,Web-Net-Ext45,Web-Request-Monitor,Web-Server,Web-Stat-Compression,Web-Static-Content,Web-Windows-Auth,Web-WMI,Windows-Identity-Foundation -Restart:$false -WarningAction Ignore
		}
		if ($script.includeEdgeTransport -eq $true)
		{
			Invoke-Command -Session $session -ScriptBlock {
				# Edge Transport server role required features
				$result = Install-WindowsFeature ADLDS -Restart:$false -WarningAction Ignore
			}
		}
        Remove-PSSession $session
        Write-Text "started."
        Restart-VirtualMachineInstance -subscription $subscription -virtualMachineService $virtualMachineService -virtualMachineName $virtualMachineName -detect $true -skipRestarts 2
        Write-Information "Virtual machine '$virtualMachineName' Exchange Server '$($script.type)' configuration ... " -NoNewLine $true
        $session = New-PSSession -ComputerName $uri[0].DnsSafeHost -Credential $credential -Port (Get-VirtualMachineInstanceEndpointPort $subscription $virtualMachineName) -UseSSL -Authentication Credssp
		Invoke-Command -Session $session -ScriptBlock {
			# Install prerequisites
            New-Item C:\ExchangeSetupLogs -Type Directory -Force | Out-Null
            if ((Start-Process -FilePath "X:\PrerequisiteInstallerFiles\UcmaRuntimeSetup.exe" -ArgumentList "/quiet /norestart /log C:\ExchangeSetupLogs\UcmaRuntimeSetup" -PassThru -Wait).ExitCode -ne 0)
            {
                throw "Exchange Server prerequisites installation failed. Check 'C:\ExchangeSetupLogs\UcmaRuntimeSetup.html' for more details."
            }
		}
	}
	"Install"
	{
		Invoke-Command -Session $session -ScriptBlock {
			param([string]$roles, [string]$organization, [string]$domainController, [string]$mdb)
			# Install binaries (verify: Get-ExchangeServer $Env:COMPUTERNAME | Format-List)
            if ((Start-Process -FilePath "X:\Setup.exe" -ArgumentList "/Mode:Install /IAcceptExchangeServerLicenseTerms /Role:$roles /OrganizationName:`"$organization`" /DomainController:`"$domainController.$($Env:USERDNSDOMAIN.ToLower())`" /MdbName:`"$mdb`" /CustomerFeedbackEnabled:False" -PassThru -Wait).ExitCode -ne 0)
            {
                throw "Exchange Server installation failed. Check 'C:\ExchangeSetupLogs\ExchangeSetup.log' for more details."
            }
		} -ArgumentList $script.roles, $script.organization, $script.domainController, $script.mdb
        Remove-PSSession $session
        Write-Text "done."
        Restart-VirtualMachineInstance $subscription $virtualMachineService $virtualMachineName $false "MSExchangeServiceHost"
        return
	}
	"Configure"
	{
		Invoke-Command -Session $session -ScriptBlock {
			param([string]$productKey, [string]$internalUrl, [string]$externalUrl, [string]$certificateName)
            # Modify Exchange PowerShell (disable banner & tips)
            $content = Get-Content "C:\Program Files\Microsoft\Exchange Server\V15\Bin\RemoteExchange.ps1" | Out-String
            $content = $content.Replace("get-exbanner `r", "#get-exbanner `r")
            $content = $content.Replace("get-tip `r", "#get-tip `r")
            $content | Out-File -LiteralPath "C:\Program Files\Microsoft\Exchange Server\V15\Bin\RemoteExchange.ps1"
            # Load Exchange PowerShell
			. "C:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1"
            Connect-ExchangeServer -Auto
            Set-Variable VerbosePreference -Value SilentlyContinue
			# Enter Product Key (Verify: (Get-ExchangeServer $Env:COMPUTERNAME).Edition)
			Set-ExchangeServer -Identity $Env:COMPUTERNAME -ProductKey $productKey
			iisreset | Out-Null
			# Create a Send connector
			$result = New-SendConnector –Name "Default Send Connector" -Internet -AddressSpaces "*" -SourceTransportServers $Env:COMPUTERNAME –MaxMessageSize 30MB
			# Configure External & Internal URLs
			$hostName = "${Env:\COMPUTERNAME}"
			Set-ClientAccessServer –Identity $hostName –AutoDiscoverServiceInternalUri "$internalUrl/Autodiscover/Autodiscover.xml"
			Set-ActiveSyncVirtualDirectory –Identity "$hostName\Microsoft-Server-ActiveSync (Default Web Site)" -InternalUrl "$internalUrl/Microsoft-Server-ActiveSync"
			Set-ActiveSyncVirtualDirectory –Identity "$hostName\Microsoft-Server-ActiveSync (Default Web Site)" –ExternalUrl "$externalUrl/Microsoft-Server-ActiveSync"
			Set-EcpVirtualDirectory –Identity "$hostName\ECP (Default Web Site)" -InternalUrl "$internalUrl/ecp"
			Set-EcpVirtualDirectory –Identity "$hostName\ecp (Default Web Site)" –ExternalUrl "$externalUrl/ecp"
			Set-WebServicesVirtualDirectory –Identity "$hostName\EWS (Default Web Site)" -InternalUrl "$internalUrl/EWS/Exchange.asmx"
			Set-WebServicesVirtualDirectory –Identity "$hostName\EWS (Default Web Site)" –ExternalUrl "$externalUrl/EWS/Exchange.asmx"
			Set-OabVirtualDirectory –Identity "$hostName\OAB (Default Web Site)" -InternalUrl "$internalUrl/OAB" 
			Set-OabVirtualDirectory –Identity "$hostName\OAB (Default Web Site)" –ExternalUrl "$externalUrl/OAB"
			Set-OwaVirtualDirectory –Identity "$hostName\OWA (Default Web Site)" -InternalUrl "$internalUrl/owa"
			Set-OwaVirtualDirectory –Identity "$hostName\OWA (Default Web Site)" –ExternalUrl "$externalUrl/owa"
			Set-PowerShellVirtualDirectory –Identity "$hostName\PowerShell (Default Web Site)" -InternalUrl "$internalUrl/powershell"
			Set-PowerShellVirtualDirectory –Identity "$hostName\PowerShell (Default Web Site)" –ExternalUrl "$externalUrl/powershell"
			# Configure an SSL certificate
            $thumbprint = (Get-Item Cert:\LocalMachine\My\* | ? {$_.FriendlyName -eq $certificateName}).Thumbprint
			Enable-ExchangeCertificate -Server $Env:COMPUTERNAME -Services "IMAP, POP, IIS, SMTP" -Thumbprint $thumbprint -Force
			# Verify at: Start-Process "https://[FQDN]/ecp" | Start-Process "https://[FQDN]/owa"
		} -ArgumentList $script.productKey, $script.internalUrl, $script.externalUrl, $script.certificateName
	}
	"Enable Mailboxes"
	{
		Invoke-Command -Session $session -ScriptBlock {
			param([string[]]$identities, [string[]]$aliases)
			. "C:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1"
            Set-Variable VerbosePreference -Value SilentlyContinue
            Connect-ExchangeServer -Auto
			for ($i = 0; $i -lt $identities.Length; $i++)
			{
				$result = Enable-Mailbox -Identity $identities[$i] -Alias $aliases[$i]
			}
		} -ArgumentList (Get-MailboxIdentities $script.mailboxes), (Get-MailboxAliases $script.mailboxes)
	}
	default
	{
		throw "Exchange Server $($script.version) type '$($script.type)' is not supported."
	}
}
Remove-PSSession $session
Write-Text "done."